package inf3791.calendarsystem.others.panels.calendar;

import eu.mpower.framework.management.patientmanagement.soap.GetPatientsForUserMessage;
import eu.mpower.framework.management.patientmanagement.soap.Patient;
import eu.mpower.framework.management.patientmanagement.soap.PatientsResponseMessage;
import eu.mpower.framework.management.patientmanagement.soap.Role;
import eu.mpower.framework.security.types.soap.SecurityToken;
import eu.mpower.mpoweractivityservice.soap.Event;
import eu.mpower.mpoweractivityservice.soap.GetActivitiesByDateRequest;
import eu.mpower.mpoweractivityservice.soap.GetActivitiesByDateResponse;
import inf3791.calendarsystem.shared.Appointment;
import inf3791.calendarsystem.shared.AuthenticationChangedListener;
import inf3791.calendarsystem.shared.AuthenticationProvider;
import inf3791.calendarsystem.shared.DaySpec;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

/**
 *
 * @author Jonas Weber
 */
public class CalendarPanel extends javax.swing.JPanel implements TableModelListener, AuthenticationChangedListener {

    private AuthenticationProvider authprovider;

    public AuthenticationProvider getAuthprovider() {
        return authprovider;
    }
    

    public void setAuthprovider(AuthenticationProvider authprovider) {
        if (this.authprovider != null) {
            this.authprovider.removeAuthenticationChangedListener(this);
        }

        this.authprovider = authprovider;

        if (this.authprovider != null) {
            this.authprovider.addAuthenticationChangedListener(this);
        }
    }
    //final static Map<DaySpec, List<Appointment>> APPOINTMENTS;
    final static Role doctor = new Role();
    final static Role daughter = new Role();

    static {
        doctor.setRolename("MS");
        daughter.setRolename("F");
    }

    static {
        /*APPOINTMENTS = new HashMap<>();
         APPOINTMENTS.put(new DaySpec(1, 10, 2012), Arrays.asList(
         new Appointment(getDateByHints(2012, 10, 01, 12, 30, 00), "Nurse visit", "Nothing special", doctor)));

         APPOINTMENTS.put(new DaySpec(5, 10, 2012), Arrays.asList(
         new Appointment(getDateByHints(2012, 10, 05, 12, 30, 00), "Nurse visit", "Nothing special", doctor),
         new Appointment(getDateByHints(2012, 10, 05, 14, 30, 00), "Son visit", "Nothing special", daughter)));*/
    }

    private static Date getDateByHints(int year, int month, int day, int hour, int minute, int seconds) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month);
        c.set(Calendar.DATE, day);

        c.set(Calendar.HOUR_OF_DAY, hour);
        c.set(Calendar.MINUTE, minute);
        c.set(Calendar.SECOND, seconds);

        return c.getTime();
    }

    /**
     * Creates new form CalendarPanel
     */
    public CalendarPanel() {
        initComponents();

        //calendarWidget1.setAppointments(APPOINTMENTS);

        ListTableModel ltm = new ListTableModel();
        tableAppointmentsDay.setModel(ltm);
        tableAppointmentsDay.setDefaultRenderer(Appointment.class, new AppointmentWidget());
        tableAppointmentsDay.setDefaultEditor(Appointment.class, new AppointmentCellEditor());

        tableAppointmentsDay.getModel().addTableModelListener(this);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        jScrollPane1 = new javax.swing.JScrollPane();
        calendarWidget1 = new inf3791.calendarsystem.others.components.calendar.CalendarWidget();
        monthSelector1 = new inf3791.calendarsystem.others.components.MonthSelector();
        dateAnnouncer1 = new inf3791.calendarsystem.others.components.DateAnnouncer();
        jScrollPane2 = new javax.swing.JScrollPane();
        tableAppointmentsDay = new javax.swing.JTable();

        jScrollPane1.setBorder(null);

        calendarWidget1.setFont(new java.awt.Font("SansSerif", 1, 30)); // NOI18N

        org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, monthSelector1, org.jdesktop.beansbinding.ELProperty.create("${month}"), calendarWidget1, org.jdesktop.beansbinding.BeanProperty.create("month"));
        bindingGroup.addBinding(binding);
        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, monthSelector1, org.jdesktop.beansbinding.ELProperty.create("${year}"), calendarWidget1, org.jdesktop.beansbinding.BeanProperty.create("year"));
        bindingGroup.addBinding(binding);

        calendarWidget1.addDayClickedListener(new inf3791.calendarsystem.others.components.calendar.DayClickedEvent.DayClickedListener() {
            public void calendarDayClicked(inf3791.calendarsystem.others.components.calendar.DayClickedEvent evt) {
                calendarWidget1CalendarDayClicked(evt);
            }
        });
        jScrollPane1.setViewportView(calendarWidget1);

        monthSelector1.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                monthSelector1PropertyChange(evt);
            }
        });

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, calendarWidget1, org.jdesktop.beansbinding.ELProperty.create("${selDaySpec}"), dateAnnouncer1, org.jdesktop.beansbinding.BeanProperty.create("date"));
        bindingGroup.addBinding(binding);

        tableAppointmentsDay.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null}
            },
            new String [] {
                "Title 1"
            }
        ));
        tableAppointmentsDay.setRowHeight(120);
        tableAppointmentsDay.setTableHeader(null);
        jScrollPane2.setViewportView(tableAppointmentsDay);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(monthSelector1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 465, Short.MAX_VALUE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(dateAnnouncer1, javax.swing.GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 441, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(33, 33, 33)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(monthSelector1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(dateAnnouncer1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 342, Short.MAX_VALUE)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        bindingGroup.bind();
    }// </editor-fold>//GEN-END:initComponents

    private void calendarWidget1CalendarDayClicked(inf3791.calendarsystem.others.components.calendar.DayClickedEvent evt) {//GEN-FIRST:event_calendarWidget1CalendarDayClicked
        ListTableModel llm = (ListTableModel) tableAppointmentsDay.getModel();
        llm.setAppointments(calendarWidget1.getAppointments().get(evt.getDaySpec()));
    }//GEN-LAST:event_calendarWidget1CalendarDayClicked

    private void monthSelector1PropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_monthSelector1PropertyChange
        // TODO add your handling code here:
    }//GEN-LAST:event_monthSelector1PropertyChange
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private inf3791.calendarsystem.others.components.calendar.CalendarWidget calendarWidget1;
    private inf3791.calendarsystem.others.components.DateAnnouncer dateAnnouncer1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private inf3791.calendarsystem.others.components.MonthSelector monthSelector1;
    private javax.swing.JTable tableAppointmentsDay;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables

    @Override
    public void tableChanged(TableModelEvent tme) {
        calendarWidget1.setAppointments(calendarWidget1.getAppointments());
    }

    @Override
    public void securityTokenChanged(SecurityToken newToken) {
        refreshAppointments(newToken, monthSelector1.getYear());
    }

    @Override
    public void securityTokenVoided() {
    }
    
    public void refreshAppointments(SecurityToken sectoken, int currentYear) {
        Map<DaySpec, List<Appointment>> appointments = new HashMap<>();

        GetPatientsForUserMessage msg = new GetPatientsForUserMessage();
        msg.setSecurityToken(sectoken);
        msg.setUserID(sectoken.getUserID());

        PatientsResponseMessage patientsresponse = getPatientsForUser(msg);

        for (Patient p : patientsresponse.getPatients()) {

            GetActivitiesByDateRequest request = new GetActivitiesByDateRequest();
            request.setSecurityToken(sectoken);
            request.setPersonId(p.getPerson().getId());

            /*Calendar c = Calendar.getInstance();
        
             c.set(Calendar.DAY_OF_YEAR, 1);
             c.set(Calendar.YEAR, currentYear);
             request.setStartDate(c.getTimeInMillis());*/

            GetActivitiesByDateResponse response = getActivitiesByDate(request);

            if (response.getStatus().getResult() == 0) {
                

                for (Event e : response.getEvents()) {
                    Appointment a = Appointment.fromEvent(e);

                    if (!appointments.containsKey(a.getDaySpec())) {
                        appointments.put(a.getDaySpec(), new LinkedList<Appointment>());
                        Logger.getLogger(CalendarPanel.class.getName()).log(Level.INFO, "Event at {0}", a.getTime().toString());
                    }

                    appointments.get(a.getDaySpec()).add(a);
                }

            } else {
                Logger.getLogger(CalendarPanel.class.getName()).log(Level.WARNING, "Could not load appointments: {0}", response.getStatus().getErrorCause());
            }

        }
        calendarWidget1.setAppointments(appointments);

        Logger.getLogger(CalendarPanel.class.getName()).log(Level.INFO, "Successfully loaded");


    }

    private static GetActivitiesByDateResponse getActivitiesByDate(eu.mpower.mpoweractivityservice.soap.GetActivitiesByDateRequest parameters) {
        eu.mpower.mpoweractivityservice.soap.ActivityWebService_Service service = new eu.mpower.mpoweractivityservice.soap.ActivityWebService_Service();
        eu.mpower.mpoweractivityservice.soap.ActivityWebService port = service.getActivityWebServicePort();
        return port.getActivitiesByDate(parameters);
    }

    private static PatientsResponseMessage getPatientsForUser(eu.mpower.framework.management.patientmanagement.soap.GetPatientsForUserMessage userIDmsg) {
        eu.mpower.framework.management.patientmanagement.soap.PatientManagement service = new eu.mpower.framework.management.patientmanagement.soap.PatientManagement();
        eu.mpower.framework.management.patientmanagement.soap.IPatientManagement port = service.getIPatientManagement();
        return port.getPatientsForUser(userIDmsg);
    }
}
